package com.ruoyi.app.api;

import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.constant.BusinessConst;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.uuid.CustomId;
import com.ruoyi.system.domain.appvo.PayAllAccount;
import com.ruoyi.system.domain.wx.WxUser;
import com.ruoyi.system.domain.wx.pay.*;
import com.ruoyi.system.service.wx.IWxUserService;
import com.ruoyi.system.service.wx.pay.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 微信支出api
 *
 * @author mic
 * @date 2023年8月14日16:15:17
 */
@RestController
@RequestMapping("/wx/pay")
public class WxPayInfoAPI extends BaseController {

    @Autowired
    private IWxPayTypeService payTypeService;
    @Autowired
    private IWxPayInfoService payInfoService;
    @Autowired
    private IWxPayUserTypeService payUserTypeService;
    @Autowired
    private IWxPayShareService shareService;
    @Autowired
    private IWxUserService userService;
    @Autowired
    private IWxPayShareMapperService shareMapperService;

    /**
     * 总流水
     *
     * @param request
     * @return
     */
    @GetMapping("/allPay")
    public AjaxResult allPay(HttpServletRequest request) {
        JSONObject json = new JSONObject();
        List<PayAllAccount> payAllAccounts = new ArrayList<>();
        PayAllAccount payAllAccount = new PayAllAccount();
        // 获取当前用户
        String userId = (String) request.getAttribute("userId");
        // 第一条支出的时间
        List<WxPayInfo> list = payInfoService.selectPayInfoDescDate(userId, 1);
        Date date = list.size() > 0 ? list.get(0).getCreateDate() : new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        json.put("time", sdf.format(date) + "起");

        // 全部支出
        WxPayInfo payInfo = new WxPayInfo();
        payInfo.setCreateBy(userId);
        List<WxPayInfo> infoList = payInfoService.selectWxPayInfoList(payInfo);
        Double payAll = infoList.stream().mapToDouble(WxPayInfo::getPayAmount).sum();
        payAllAccount.setName("全部支出");
        payAllAccount.setValue(payAll + "");
        payAllAccounts.add(payAllAccount);
        payAllAccount = new PayAllAccount();

        // 今年支出
        Map<String, Object> map = new HashMap<>();
        map.put("userId", userId);
        map.put("date", new Date());
        List<WxPayInfo> yearList = payInfoService.selectPayInfoListByYear(map);
        Double yearAll = yearList.stream().mapToDouble(WxPayInfo::getPayAmount).sum();
        payAllAccount.setName("今年支出");
        payAllAccount.setValue(yearAll + "");
        payAllAccounts.add(payAllAccount);
        payAllAccount = new PayAllAccount();

        // 本月支出
        List<WxPayInfo> monthList = payInfoService.selectPayInfoListByMonth(map);
        Double monthAll = monthList.stream().mapToDouble(WxPayInfo::getPayAmount).sum();
        payAllAccount.setName("本月支出");
        payAllAccount.setValue(monthAll + "");
        payAllAccounts.add(payAllAccount);
        payAllAccount = new PayAllAccount();

        // 今日支出
        List<WxPayInfo> dayList = payInfoService.selectPayInfoListByDay(map);
        Double dayAll = dayList.stream().mapToDouble(WxPayInfo::getPayAmount).sum();
        payAllAccount.setName("今日支出");
        payAllAccount.setValue(dayAll + "");
        payAllAccounts.add(payAllAccount);
        json.put("list", payAllAccounts);
        return AjaxResult.success("获取总流水成功!", json);
    }

    /**
     * 分享的总流水
     */
    @RequestMapping("/shareAllPay")
    public AjaxResult shareAllPay(HttpServletRequest request) {
        JSONObject all = new JSONObject();
        // 获取当前用户
        String userId = (String) request.getAttribute("userId");
        SimpleDateFormat year = new SimpleDateFormat("yyyy");
        SimpleDateFormat month = new SimpleDateFormat("yyyy-MM");
        SimpleDateFormat day = new SimpleDateFormat("yyyy-MM-dd");

        // 获取分享给我的数据
        WxPayShare share = new WxPayShare();
        share.setViewBy(userId);
        List<WxPayShare> shares = shareService.selectWxPayShareList(share);
        List<WxPayInfo> infos = new ArrayList<>();
        // shareInfo 数据合并
        for (int i = 0; i < shares.size(); i++) {
            WxPayInfo info = payInfoService.selectWxPayInfoByPayId(shares.get(i).getPayId());
            infos.add(info);
        }
        Map<String, List<WxPayInfo>> infoBy = infos.stream().collect(Collectors.groupingBy(WxPayInfo::getCreateBy));    //按支出明细创建者分组
        JSONObject json = new JSONObject();
        List<PayAllAccount> allAccounts = new ArrayList<>();  // 合计的 self
        PayAllAccount alla = new PayAllAccount();
        PayAllAccount yeara = new PayAllAccount();
        PayAllAccount montha = new PayAllAccount();
        PayAllAccount daya = new PayAllAccount();
        List<JSONObject> list = new ArrayList<>();
        for (String key : infoBy.keySet()) {
            List<WxPayInfo> wxPayInfos = infoBy.get(key);
            List<PayAllAccount> l = new ArrayList<>();
            PayAllAccount a = new PayAllAccount();
            PayAllAccount y = new PayAllAccount();
            PayAllAccount m = new PayAllAccount();
            PayAllAccount d = new PayAllAccount();
            JSONObject inJson = new JSONObject();
            // 全部
            double sum = wxPayInfos.stream().mapToDouble(WxPayInfo::getPayAmount).sum();
            a.setName("全部支出");
            a.setValue(sum + "");

            if (StringUtils.isBlank(alla.getName())) {
                alla.setName("全部支出");
            }
            double allSum = StringUtils.isBlank(alla.getValue()) ? sum : Double.parseDouble(alla.getValue()) + sum;
            alla.setValue(allSum + "");
            alla.setTime(day.format(shares.get(0).getCreateTime()));

            // 本年
            List<WxPayInfo> yearList = wxPayInfos.stream().filter(x -> year.format(x.getCreateDate()).equals(year.format(new Date())))
                    .collect(Collectors.toList());
            double yearSum = yearList.stream().mapToDouble(WxPayInfo::getPayAmount).sum();
            y.setName("今年支出");
            y.setValue(yearSum + "");

            if (StringUtils.isBlank(yeara.getName())) {
                yeara.setName("今年支出");
            }
            double years = StringUtils.isBlank(yeara.getValue()) ? yearSum : Double.parseDouble(yeara.getValue()) + yearSum;
            yeara.setValue(years + "");

            // 本月
            List<WxPayInfo> monthList = wxPayInfos.stream().filter(x -> month.format(x.getCreateDate()).equals(month.format(new Date())))
                    .collect(Collectors.toList());
            double monthSum = monthList.stream().mapToDouble(WxPayInfo::getPayAmount).sum();
            m.setName("本月支出");
            m.setValue(monthSum + "");

            if (StringUtils.isBlank(montha.getName())) {
                montha.setName("本月支出");
            }
            double months = StringUtils.isBlank(montha.getValue()) ? monthSum : Double.parseDouble(montha.getValue()) + monthSum;
            montha.setValue(months + "");

            // 今日
            List<WxPayInfo> dayList = wxPayInfos.stream().filter(x -> day.format(x.getCreateDate()).equals(day.format(new Date())))
                    .collect(Collectors.toList());
            double daySum = dayList.stream().mapToDouble(WxPayInfo::getPayAmount).sum();
            d.setName("今日支出");
            d.setValue(daySum + "");

            if (StringUtils.isBlank(daya.getName())) {
                daya.setName("今日支出");
            }
            double days = StringUtils.isBlank(daya.getValue()) ? daySum : Double.parseDouble(daya.getValue()) + daySum;
            daya.setValue(days + "");

            l.add(a);
            l.add(y);
            l.add(m);
            l.add(d);
            // 昵称或id
            String nickName = "";
            WxPayShareMapper shareMapper = new WxPayShareMapper();
            shareMapper.setBelongBy(userId);
            shareMapper.setViewBy(key);
            shareMapper.setStatus("0");
            List<WxPayShareMapper> wxPayShareMappers = shareMapperService.selectWxPayShareMapperList(shareMapper);
            if (wxPayShareMappers != null && wxPayShareMappers.size() > 0) {
                if (StringUtils.isBlank(wxPayShareMappers.get(0).getViewName())) {   // 备注为空
                    WxUser user = new WxUser();
                    user = userService.selectWxUserByUserId(key);
                    if (user != null) {
                        nickName = "用户ID:" + user.getViewId();
                    } else {
                        nickName = "用户编码:" + key.substring(key.length() - 8, key.length());
                    }
                } else {
                    nickName = wxPayShareMappers.get(0).getViewName();
                }
            } else {
                nickName = key;
            }
            inJson.put(nickName,l);
            list.add(inJson);
        }
        allAccounts.add(alla);
        allAccounts.add(yeara);
        allAccounts.add(montha);
        allAccounts.add(daya);
        json.put("list", list);
        json.put("sum", allAccounts);
        return AjaxResult.success(json);
    }


    /**
     * 根据年或年月获取echarts数据
     *
     * @param date        根据日期查询
     * @param dateType    日期类型 'y'年 'm'月
     * @param shareUserId 根据userid查询
     */
    @GetMapping("/yearChart")
    public AjaxResult yearChart(HttpServletRequest request, String date, String dateType, String shareUserId) {
        Date time;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        // 获取用户
        String userId = (String) request.getAttribute("userId");
        if (StringUtils.isNotBlank(shareUserId)) {
            userId = shareUserId;
        }


        // 获取数据
        List<WxPayInfo> wxPayInfos = new ArrayList<>();
        Map<String, Object> map = new HashMap<>();
        map.put("userId", userId);
        if (BusinessConst.EchartsType.YEAR.equals(dateType)) {
            // 年份查询
            try {
                time = StringUtils.isNotBlank(date) ? sdf.parse(date + "-02-02") : new Date();
            } catch (ParseException e) {
                time = new Date();
                logger.info("日期转换错误");
            }
            map.put("date", time);
            wxPayInfos = payInfoService.selectPayInfoListByYear(map);

        } else if (BusinessConst.EchartsType.MONTH.equals(dateType)) {
            // 月份查询
            try {
                time = StringUtils.isNotBlank(date) ? sdf.parse(date + "-02") : new Date();
            } catch (ParseException e) {
                time = new Date();
                logger.info("日期转换错误");
            }
            map.put("date", time);
            wxPayInfos = payInfoService.selectPayInfoListByMonth(map);
        }
        String sum = wxPayInfos.stream().mapToDouble(WxPayInfo::getPayAmount).sum() + "";
        // echarts 数据机构
        List<PayAllAccount> payAllAccounts = payInfoService.groupTypeSum(wxPayInfos);
        JSONObject json = new JSONObject();
        json.put("list", payAllAccounts);
        json.put("sum", sum);
        // top5
        List<PayAllAccount> limit = new ArrayList<>(5);
        Integer size = payAllAccounts.size() < 5 ? payAllAccounts.size() : 5;
        for (int i = 0; i < size; i++) {
            limit.add(payAllAccounts.get(i));
        }
        json.put("topList", limit);

        return AjaxResult.success(json);
    }

    /**
     * 折线图
     */
    @RequestMapping("/lineChart")
    public AjaxResult lineChart(HttpServletRequest request, String shareUserId) {
        // 获取用户
        String userId = (String) request.getAttribute("userId");
        if (StringUtils.isNotBlank(shareUserId)) {
            userId = shareUserId;
        }
        WxPayInfo payInfo = new WxPayInfo();
        payInfo.setCreateBy(userId);
        List<Map<String, Double>> year = payInfoService.selectInfoGroupYear(payInfo);
        List<Map<String, Double>> month = payInfoService.selectInfoGroupMonth(payInfo);
        JSONObject json = new JSONObject();
        json.put("yearLineChart", year);
        json.put("monthLineChart", month);
        return AjaxResult.success(json);
    }

    /**
     * 明细列表数据
     */
    @GetMapping("/detailList")
    public AjaxResult detailList(HttpServletRequest request) {
        // 获取用户
        String userId = (String) request.getAttribute("userId");
        // 获取数据,且格式化日期
        WxPayInfo payInfo = new WxPayInfo();
        payInfo.setCreateBy(userId);
        List<WxPayInfo> infos = payInfoService.selectWxPayInfoList(payInfo);
        SimpleDateFormat sf = new SimpleDateFormat(DateUtils.YYYY_MM_DD);
        for (int i = 0; i < infos.size(); i++) {
            infos.get(i).setCreateDateStr(sf.format(infos.get(i).getCreateDate()));
        }

        // 按日期分组
        Map<String, List<WxPayInfo>> collect = infos.stream().collect(Collectors.groupingBy(WxPayInfo::getCreateDateStr));
        Set<String> str = collect.keySet();
        List<String> list = new ArrayList<>(str);
        Collections.sort(list, Collections.reverseOrder());
        Integer limit = list.size() >= 5 ? 5 : list.size();
        list = list.subList(0, limit);

        // 求和
        List<JSONObject> jsonList = new ArrayList<>();
        SimpleDateFormat nyrsf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        for (int i = 0; i < list.size(); i++) {
            List<JSONObject> jsonDay = new ArrayList<>();
            // 条明细
            List<WxPayInfo> infoList = collect.get(list.get(i));
            for (int j = 0; j < infoList.size(); j++) {
                WxPayType wxPayType = payTypeService.selectWxPayTypeByTypeId(infoList.get(j).getPrimaryType());
                WxPayType parentType = payTypeService.selectWxPayTypeByTypeId(wxPayType.getParentId());
                JSONObject json = new JSONObject();
                json.put("name", parentType.getTypeName() + "-" + wxPayType.getTypeName());
                json.put("time", nyrsf.format(infoList.get(j).getCreateDate()));
                json.put("value", infoList.get(j).getPayAmount());
                json.put("payId", infoList.get(j).getPayId());
                jsonDay.add(json);
            }
            // 外列属性
            String sum = infoList.stream().mapToDouble(WxPayInfo::getPayAmount).sum() + "";
            JSONObject jsonD = new JSONObject();
            jsonD.put("date", list.get(i));
            jsonD.put("payout", sum);
            jsonD.put("list", jsonDay);
            jsonList.add(jsonD);
        }
        return AjaxResult.success(jsonList);
    }

    /**
     * 新增 修改接口
     *
     * @param request
     * @param info    新增实体
     * @return
     */
    @PostMapping("/insert")
    public AjaxResult insert(HttpServletRequest request, WxPayInfo info) {
        // 时间格式化
        if (StringUtils.isNotBlank(info.getCreateDateStr())) {
            long times = Long.parseLong(info.getCreateDateStr());
            info.setCreateDate(new Date(times));
        } else {
            info.setCreateDate(new Date());

        }
        // 金额和类型不能为空
        if (StringUtils.isBlank(info.getPrimaryType()) || info.getPayAmount() == null) {
            return AjaxResult.error("金额或者类型不能为空!");
        }
        // 放入属性
        info.setCreateBy((String) request.getAttribute("userId"));
        info.setUpdateBy((String) request.getAttribute("userId"));
        info.setUpdateDate(new Date());
        if (StringUtils.isNotBlank(info.getPayId())) {
            // 常用类型
            WxPayInfo oldInfo = payInfoService.selectWxPayInfoByPayId(info.getPayId());
            payUserTypeService.updateCategoryByInfo(info, oldInfo);
            // 修改
            payInfoService.updateWxPayInfo(info);
        } else {
            // 新增
            info.setPayId("p" + CustomId.timestamp());
            payInfoService.insertWxPayInfo(info);
            // 常用类型
            payUserTypeService.updateCategoryByInfo(info, null);
        }
        // 账单分享
        String[] shares = info.getShareBy().split(",");
        if (!BusinessConst.YesOrNo.NO.equals(shares[0])) {
            // 分享
            // 删除之前的分享记录
            shareService.deleteWxPayShareByPayId(info.getPayId());

            // 新增 新的记录
            for (int i = 0; i < shares.length; i++) {
                WxPayShare payShare = new WxPayShare();
                payShare.setPayId(info.getPayId());
                payShare.setShareId("s" + CustomId.timestamp());
                payShare.setStatus(BusinessConst.YesOrNo.NO);
                payShare.setCreateBy((String) request.getAttribute("userId"));
                payShare.setViewBy(shares[i]);
                payShare.setCreateTime(new Date());
                shareService.insertWxPayShare(payShare);
            }


        }
        return AjaxResult.success("操作成功!");
    }

    /**
     * 单条回显数据
     */
    @RequestMapping("/getInfo")
    public AjaxResult getInfo(WxPayInfo info) {
        if (StringUtils.isBlank(info.getPayId())) {
            return AjaxResult.error("服务器没有接收到明细编码!");
        } else {
            WxPayInfo wxPayInfo = payInfoService.selectWxPayInfoByPayId(info.getPayId());
            if (wxPayInfo == null) {
                return AjaxResult.error("未获取到有用数据!");
            } else {
                return AjaxResult.success(wxPayInfo);
            }
        }
    }

    /**
     * 删除接口
     */
    @RequestMapping("/delInfo")
    private AjaxResult delInfo(HttpServletRequest request, WxPayInfo info) {
        // 用户
        String userId = (String) request.getAttribute("userId");
        if (StringUtils.isBlank(userId)) {
            return AjaxResult.error("未获取到该用户!");
        }

        // 数据是否属于该用户
        WxPayInfo wxPayInfo = payInfoService.selectWxPayInfoByPayId(info.getPayId());
        if (wxPayInfo != null && wxPayInfo.getCreateBy().equals(userId)) {
            // 用户匹配
            wxPayInfo.setStatus(BusinessConst.YesOrNo.YES);
            payInfoService.updateWxPayInfo(wxPayInfo);
            // 处理常用类型表
            payUserTypeService.updateCategoryByInfo(null, wxPayInfo);
            return AjaxResult.success(wxPayInfo);
        } else {
            return AjaxResult.error("未获取到有用数据!");
        }
    }

    /**
     * 新增时 - 常用分类
     */
    @RequestMapping("/getCustomCategory")
    private AjaxResult getCustomCategory(HttpServletRequest request) {
        // 用户
        String userId = (String) request.getAttribute("userId");
        WxPayUserType type = new WxPayUserType();
        type.setCreateBy(userId);
        List<WxPayUserType> list = payUserTypeService.selectWxPayUserTypeList(type);
        List<JSONObject> typeList = new ArrayList<>();
        Integer limit = 0;
        if (list != null && list.size() > 0) {
            // 过滤今天的数据
            for (int i = 0; i < list.size(); i++) {
                if (!DateUtils.judgeToday(list.get(i).getUpdateTime()) && limit < 5) {
                    // 不是今天的数据
                    WxPayType wxPayType = payTypeService.selectWxPayTypeByTypeId(list.get(i).getTypeId());
                    list.get(i).setTypeName(wxPayType.getTypeName());
                    JSONObject json = new JSONObject();
                    json.put("code", wxPayType.getTypeId());
                    json.put("label", wxPayType.getTypeName());
                    typeList.add(json);
                    limit++;
                }
            }
        }
        return AjaxResult.success(typeList);

    }


    /**
     * 首页 资产概括
     */
    @RequestMapping("/sumup")
    public AjaxResult sumip(HttpServletRequest request, String userId) {
        if (StringUtils.isBlank(userId)) {
            userId = (String) request.getAttribute("userId");
        }

        // 查询支出数据
        WxPayInfo info = new WxPayInfo();
        info.setCreateBy(userId);
        info.setStatus("0");
        List<WxPayInfo> list = payInfoService.selectWxPayInfoList(info);
        double sum = list.stream().mapToDouble(WxPayInfo::getPayAmount).sum();
        JSONObject json = new JSONObject();
        json.put("pay", sum);

        // TODO 收入和其他的模块没有做
        json.put("residue", 0 - sum);

        return AjaxResult.success(json);

    }

    /**
     * 首页 指定年月的  月汇总数据
     */
    @RequestMapping("/sumupByMonth")
    public AjaxResult sumupByMonth(HttpServletRequest request, String userId, String dateStr) {
        SimpleDateFormat year = new SimpleDateFormat("yyyy");
        SimpleDateFormat month = new SimpleDateFormat("MM");
        if (StringUtils.isBlank(userId)) {
            userId = (String) request.getAttribute("userId");
        }
        if (StringUtils.isBlank(dateStr)) {
            dateStr = year.format(new Date());
        } else {

        }

        // 支出
        WxPayInfo info = new WxPayInfo();
        info.setStatus("0");
        info.setCreateBy(userId);
        info.setCreateDateStr(dateStr);
        List<WxPayInfo> list = payInfoService.selectByYearList(info);
        for (int i = 0; i < list.size(); i++) {
            list.get(i).setCreateDateStr(month.format(list.get(i).getCreateDate()));
        }
        Map<String, List<WxPayInfo>> infos = list.stream().collect(Collectors.groupingBy(WxPayInfo::getCreateDateStr));
        JSONObject object = new JSONObject();
        List<JSONObject> jsonList = new ArrayList<>();
        JSONObject js = new JSONObject();
        Double sumPay = list.stream().mapToDouble(WxPayInfo::getPayAmount).sum();
        js.put("pay", sumPay);
        js.put("income", 0D);
        js.put("residue", 0D - sumPay);
        object.put("content", js);
        int max = Integer.parseInt(month.format(new Date()));   // 当前月
        // 若不是本年 则月数显示1-12
        if (!dateStr.equals(year.format(new Date()))) {
            max = 12;
        }
        List<String> months = new ArrayList<>();
        for (int i = 0; i < max; i++) {
            if (i >= 9) {
                months.add(i + 1 + "");
            } else {
                months.add("0" + (i + 1));
            }
        }
        Collections.reverse(months);
        for (int j = 0; j < months.size(); j++) {
            Boolean flag = true;
            JSONObject json = new JSONObject();
            for (String key : infos.keySet()) {
                if (key.equals(months.get(j))) {
                    double sum = infos.get(key).stream().mapToDouble(WxPayInfo::getPayAmount).sum();
                    json.put("month", key + "月");
                    json.put("pay", sum);
                    json.put("income", 0D);
                    json.put("residue", 0D - sum);
                    jsonList.add(json);
                    flag = false;
                }
            }
            if (flag) {
                json.put("month", months.get(j) + "月");
                json.put("pay", 0);
                json.put("income", 0);
                json.put("residue", 0);
                jsonList.add(json);
            }
        }

        object.put("list", jsonList);

        return AjaxResult.success(object);
    }
}
